from abc import ABC, abstractmethod
from ..schema.memory import Memory
from ..tool.base import BaseTool
from ..schema.agent_state import AgentState


class BaseAgent(ABC):
    def __init__(self):
        self.state = AgentState.IDLE.value
        self.memory = Memory()
        self.available_tools = {}

    def add_tool(self, tool_class, tool_instance):
        if not (isinstance(tool_instance, BaseTool) and issubclass(tool_class, BaseTool)):
            raise ValueError("Invalid tool class or instance")
        self.available_tools[tool_class.__name__] = tool_instance

    def run(self):
        self.state = AgentState.RUNNING.value
        while self.state == AgentState.RUNNING.value:
            self.step()

    @abstractmethod
    def step(self):
        pass


class ReActAgent(BaseAgent):
    def step(self):
        action = self.think()
        self.act(action)

    @abstractmethod
    def think(self) -> str:
        pass

    @abstractmethod
    def act(self, action: str):
        pass


class ToolCallAgent(ReActAgent):
    def call_tool(self, name: str, arguments: dict) -> str:
        tool = self.available_tools.get(name)
        if not tool:
            return f"Tool {name} not found"
        try:
            return tool.execute(arguments)
        except Exception as e:
            return f"Error executing tool {name}: {str(e)}"
